/******************************************************************************
 * Copyright (C), 2014, BeeIoT Tech. Co., Ltd. 
 * FileName:        stat.c
 * Author:          lvxin 
 * Version :        1.0
 * Date:            2017-01-12 04:14:38
 * Description:
 * Function List:   1. -------
 * History:
 * <author>     <time>                <version >  <desc> 
 * lvxin        2017-01-12 04:14:38   1.0         build this moudle 
 *****************************************************************************/

/******************************************************************************
 *  *INCLUDES
 *  */
#include "stat.h"

/******************************************************************************
 *  *TYPEDEFS
 *  */
typedef void (*handle_t)(stat_t *st, int ch, int num, void *arg);   //状态处理函数

/******************************************************************************
 *  *FUNCTION DECLARES
 *  */
static void handle_data(stat_t *st, int ch, int num, void *arg);
static void handle_length(stat_t *st, int ch, int num, void *arg);
static void handle_start(stat_t *st, int ch, int num, void *arg);

/******************************************************************************
 *  *LOCAL CONSTANCE VARIABLES
 *  */
static const handle_t proto[]={  //状态机处理函数
    handle_start,
    handle_length,
    handle_data,
};

/******************************************************************************
 *  *PUBLIC FUNCTIONS
 *  */
int proto_init(stat_t *st, callback_t callback, void *arg)
{
    if (st == NULL) return -1;
    st->remain = 0;
    st->current_stat = REC_START;
    st->callback = callback;
    st->arg = arg;
    return 0;
}

int inline proto_proc(stat_t *st, int ch)
{
    if (st == NULL) return -1;
    proto[st->current_stat](st, ch, 0, NULL);
    return 0;
}

/******************************************************************************
 *  *LOCAL FUNCTIONS
 *  */

//状态转换
static inline void _stat_change(stat_t *st, stat_em_t stat, int data_len)
{
    st->current_stat = stat;
    st->remain = data_len;
}

static void handle_start(stat_t *st, int ch, int num, void *arg)
{
    if (ch == 0xAA) //判断起始标识
    {
        _stat_change (st, REC_LENGTH, 1);  //切换状态
    }
    /*printf ("[0]data: 0x%02X\tIdle\n", ch);*/
}

static void handle_length(stat_t *st, int ch, int num, void *arg)
{
    st->remain -= 1;
    if ((st->remain <= 0) && (ch != 0))
    {
        _stat_change (st, REC_DATA, ch);  //切换状态
        st->package.len = 0;
    }
    else
    {
        _stat_change (st, REC_START, 0);
    }
    /*printf ("[1]data: 0x%02X\tGetLen\n", ch);*/
}

static void handle_data(stat_t *st, int ch, int num, void *arg)
{
    /*printf ("[2]data: 0x%02X\tData\n", ch);*/
    st->package.data[st->package.len] = ch;
    st->package.len ++;
    st->remain --;
    if (st->remain <= 0 || st->package.len > DATA_MAX_LEN)
    {
        st->package.len = (st->package.len > DATA_MAX_LEN)?
            DATA_MAX_LEN:st->package.len; //len重新赋值
        st->callback(st->package.data, st->package.len, st->arg);
        _stat_change (st, REC_START, 0);
        return;
    }
}
